package com.peas.platform.common.core.component;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.StopWatch;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.net.url.UrlBuilder;
import cn.hutool.core.net.url.UrlQuery;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.peas.platform.common.core.configuration.RequestContextUtil;
import com.peas.platform.common.core.dto.ResponseDto;
import com.peas.platform.common.core.feign.PeasModuleSysCoreFeign;
import com.peas.platform.common.core.utils.LogUtil;
import com.peas.platform.common.core.utils.SystemTool;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;

@Component
@Slf4j
public class HttpClientCall {

    @Value("${spring.profiles.active:local}")
    private String profiles;
    @Resource
    private PeasModuleSysCoreFeign peasModuleSysCoreFeign;
    @Resource
    private SystemTool systemTool;

    public String get(String sys, String url, Map<String, Object> param, String body, String contentType, Map<String, String> header) {
        return execute(Method.GET, sys, url, param, body, contentType, header);
    }

    public String post(String sys, String url, String body, String contentType, Map<String, String> header) {
        return execute(Method.POST, sys, url, null, body, contentType, header);
    }

    public String put(String sys, String url, String body, String contentType, Map<String, String> header) {
        return execute(Method.PUT, sys, url, null, body, contentType, header);
    }

    public String delete(String sys, String url, String body, String contentType, Map<String, String> header) {
        return execute(Method.DELETE, sys, url, null, body, contentType, header);
    }

    public String execute(final Method method, final String sys, final String url, Map<String, Object> param, String body, final String contentType, final Map<String, String> header) {
        Assert.notBlank(sys, "sys不能为空");
        StopWatch sw = new StopWatch();
        sw.start();
        UrlBuilder ub = UrlBuilder.of(url);
        if (CollUtil.isNotEmpty(param)) {
            ub.setQuery(UrlQuery.of(param));
        }
        HttpRequest req = HttpRequest.of(ub).method(method);
        req.body(body);
        req.contentType(contentType);
        if (CollUtil.isNotEmpty(header)) {
            for (Map.Entry<String, String> entry : header.entrySet()) {
                req.header(entry.getKey(), entry.getValue());
            }
        }
        String resp = null;
        try (HttpResponse response = req.execute()) {
            resp = response.body();
            return resp;
        } finally {
            sw.stop();
            if (!StrUtil.equals("local", profiles)) {
                final String traceId = RequestContextUtil.getCurrentRequestId();
                JSONObject json = new JSONObject();
                json.set("sys", sys);
                json.set("url", url);
                json.set("traceId", traceId);
                json.set("contentType", contentType);
                json.set("header", header);
                json.set("body", body);
                json.set("resp", resp);
                json.set("duration", sw.getTotalTimeMillis());
                new FutureTaskCall<JSONObject, Boolean>().submitAsync(o -> {
                    HttpClientCall.this.call(o.getStr("sys"),
                            o.getStr("url"),
                            o.getStr("traceId"),
                            o.getStr("contentType"),
                            o.getJSONObject("header"),
                            o.getStr("body"),
                            o.getStr("resp"),
                            o.getLong("duration"));
                    return true;
                }, json);
            }
        }
    }

    private void call(String sys, String url, String traceId, String contentType, JSONObject header, String body, String resp, long duration) {
        if (systemTool.special()) {
            LogUtil.log(this.getClass(), "call", "sys:" + sys + ",url" + url + ",traceId:" + traceId + ",contentType:" + contentType + ",header:" + header + ",body:" + body + ",resp:" + resp, duration);
            return;
        }
        JSONObject data = systemTool.buildJSONObject();
        data.set("sys", sys);
        data.set("url", url);
        data.set("contentType", contentType);
        data.set("requestHeader", StrUtil.sub(JSONUtil.toJsonStr(header), 0, 2000));
        data.set("requestBody", StrUtil.sub(body, 0, 2000));
        data.set("responseBody", StrUtil.sub(resp, 0, 2000));
        data.set("callRequestId", traceId);
        data.set("callTime", new Date());
        data.set("callDuration", duration);
        log.debug("call peasModuleSysMdmFeign.addCall:" + JSONUtil.toJsonStr(data));
        ResponseDto<Integer> result = peasModuleSysCoreFeign.addCall(data);
        log.debug("call peasModuleSysMdmFeign.addCall, result:" + result);
    }

}
